#ifndef REACTORACCEPTOR_H
#define REACTORACCEPTOR_H

#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"

#include "./Common.h"

class ServerFactory;

namespace Reactor
{
	template <class SocketReactorDispatcher>
	class ReactorAcceptor
	{
	public:
		using Observer = Poco::Observer<ReactorAcceptor, Poco::Net::ReadableNotification>;
		ReactorAcceptor(Poco::Net::ServerSocket& socket, std::shared_ptr<ServerFactory> _serverFactory, const SessionOp& _sessionop);
		ReactorAcceptor(Poco::Net::ServerSocket& socket, std::shared_ptr<ServerFactory> _serverFactory, Poco::Net::SocketReactor& reactor, const SessionOp& _sessionop);
		ReactorAcceptor() = delete;
		ReactorAcceptor(const ReactorAcceptor&) = delete;
		ReactorAcceptor& operator = (const ReactorAcceptor&) = delete;
		virtual ~ReactorAcceptor();

	public:
		void setReactor(Poco::Net::SocketReactor& reactor);
		virtual void registerAcceptor(Poco::Net::SocketReactor& reactor);
		virtual void unregisterAcceptor();
		void onAccept(Poco::Net::ReadableNotification* pNotification);
		SocketReactorDispatcher* reactorDispatcher() const;
		void setSocketReactorDispatcher(std::shared_ptr<SocketReactorDispatcher> dispatcher);

	protected:
		void createServiceHandler(Poco::Net::StreamSocket& socket);
		Poco::Net::SocketReactor* reactor();
		Poco::Net::Socket& socket();

	private:
		const SessionOp _sessionop;
		std::shared_ptr<ServerFactory> _serverFactory;
		Poco::Net::ServerSocket&   _socket;
		Poco::Net::SocketReactor* _pReactor{ nullptr };
		std::shared_ptr<SocketReactorDispatcher> _pSocketReactorDispatcher{ nullptr };
	};
}

#include "./ReactorAcceptor.inl"


#endif // !REACTORACCEPTOR_H
